<?php

namespace services\rbac;

use Yii;
use common\components\Service;
use common\models\member\Member;
use common\models\rbac\Module;
use common\models\rbac\UserRole;
use common\models\rbac\Role;
use common\models\rbac\RolePermission;
use common\helpers\CommonHelper;
use api\modules\v1\forms\rbac\RoleForm;

/**
 * Class RoleService
 * @package services\rbac
 */
class RoleService extends Service
{
    /**
     * 根据ID查找角色信息
     *
     * @param int $id
     * @return Role|null
     */
    public function findById(int $id = 0): ?Role
    {
        return Role::find()->where(['id' => $id])->one();
    }

    /**
     * 查找角色信息
     *
     * @param array $condition
     * @return Role|null
     */
    public function findInfo(array $condition = []): ?Role
    {
        $query = Role::find();

        isset($condition['project_id']) && $query->andWhere(['project_id' => $condition['project_id']]);
        isset($condition['name']) && $query->andWhere(['name' => $condition['name']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);

        return $query->one();
    }

    /**
     * 查找列表
     *
     * @param array $condition
     * @return array|\yii\db\ActiveRecord[]
     */
    public function findList(array $condition = [])
    {
        $query = Role::find();

        // select
        isset($condition['select']) && $query->select($condition['select']);

        // condition
        isset($condition['id']) && $query->andWhere(['id' => $condition['id']]);
        isset($condition['project_id']) && $query->andWhere(['project_id' => $condition['project_id']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);
        isset($condition['other']) && $query->andWhere($condition['other']);

        return $query->asArray()->all();
    }

    /**
     * 角色列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @param int $isSystem 是否系统角色【1是、0否（全部）】
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0, int $isSystem = 0)
    {
        $query = Role::find()->select(['*'])
            ->where([
                'status' => [Role::STATUS_INVALID, Role::STATUS_ENABLE],
            ]);

        if ($isSystem == 1) {// 系统角色
            $query->andWhere(['type' => Role::TYPE_INLAY]);
        } else {// 全部角色
            $query->andWhere([
                'or',
                ['project_id' => $params['project_id']],
                ['type' => Role::TYPE_INLAY]
            ]);
        }

        // 总数
        $total = $query->count();

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query
            ->orderBy(['type' => SORT_DESC, 'status' => SORT_DESC, 'sort' => SORT_ASC, 'id' => SORT_DESC])
            ->asArray()
            ->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }

    /**
     * 格式化列表数据
     *
     * @param array $data
     * @param int $isSystem
     * @param int $projectId
     * @return array
     */
    public function getListPageFormat(array $data, int $isSystem = 0, int $projectId = 0)
    {
        // 绑定角色数量
        $roleIdArr = array_column($data, 'id');
        $condition = [
            'and',
            ['a.role_id' => $roleIdArr],
            ['b.status' => Member::STATUS_ENABLE]
        ];
        if ($isSystem == 0) {
            $condition[] = ['a.project_id' => $projectId];
        }
        $userRoleCountList = UserRole::find()
            ->alias('a')
            ->leftJoin(Member::tableName() . ' AS b', 'a.member_id = b.id')
            ->select(['count(a.id) as count_member', 'a.role_id'])
            ->where($condition)
            ->groupBy('a.role_id')
            ->indexBy('role_id')
            ->asArray()
            ->all();

        $list = [];
        foreach ($data as $key => $row) {
            $isEdit = 0;
            if (($row['type'] == Role::TYPE_NOMAL && $isSystem == 0)
                || ($isSystem == 1 && Yii::$app->user->identity->member->is_super == Member::IS_SUPER_YES)
            ) {
                $isEdit = 1;
            }

            $list[$key] = [
                'id' => $row['id'],
                'project_id' => $row['project_id'],
                'name' => $row['name'],
                'desc' => $row['desc'],
                'type' => $row['type'],
                'type_str' => Role::$types[$row['type']],
                'status' => $row['status'],
                'status_str' => Role::$statuss[$row['status']],
                'is_edit' => $isEdit,
                'count_member' => $userRoleCountList[$row['id']]['count_member'] ?? 0,
            ];
        }

        return $list;
    }

    /**
     * 获取角色权限列表
     *
     * @param int $roleId
     * @return array
     */
    public function getRoleAuthList(int $roleId = 0)
    {
        // 角色权限
        $rolePermission = Yii::$app->services->rolePermission->findList(['role_id' => $roleId]);
        $roleAuthList = [
            'module' => [],
            'menu' => [],
            'action' => [],
        ];
        foreach ($rolePermission as $row) {
            if ($row['permission_type'] == RolePermission::PERMISSION_TYPE_MENU) {
                $roleAuthList['menu'][] = $row['permission_id'];
            } else if ($row['permission_type'] == RolePermission::PERMISSION_TYPE_ACTION) {
                $roleAuthList['action'][] = $row['permission_id'];
            } else {
                $roleAuthList['module'][] = $row['permission_id'];
            }
        }

        // 权限列表【菜单+动作】
        $authList = Yii::$app->services->menu->getInnerActionList();

        // 模块列表
        $moduleList = Module::find()
            ->where([
                'status' => Module::STATUS_ENABLE
            ])
            ->asArray()
            ->all();

        // 格式化权限列表
        $authListData = Yii::$app->services->menu->getInnerActionListFormat($authList, 0, $roleAuthList);

        $authListFormat = [];
        foreach ($moduleList as $row) {
            // 父菜单
            $item = [
                'value' => $row['id'],
                'title' => $row['name'],
                'permission_type' => RolePermission::PERMISSION_TYPE_MODULE,
                'expand' => !empty($authListData[$row['id']]),
                // 'checked' => in_array($row['id'], $menuAuth),
                // 'children' => $children,
            ];
            // 底层返回checked属性
            if (empty($authListData[$row['id']])) {
                $item['checked'] = in_array($row['id'], $roleAuthList['module']);
            }
            $item['children'] = $authListData[$row['id']] ?? [];

            $authListFormat[] = $item;
        }

        return $authListFormat;
    }

    /**
     * 新增角色
     *
     * @param RoleForm $model
     * @return array|mixed
     */
    public function create(RoleForm $model)
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            // 1.新增角色
            $role = new Role();
            $role->project_id = $model->type == Role::TYPE_NOMAL ? $model->project_id : 0;
            $role->name = $model->name;
            $role->desc = $model->desc;
            $role->type = $model->type;
            $role->status = $model->status;
            $role->save();

            // 2-1.添加角色菜单权限
            foreach ($model->getAddMenuIds() as $row) {
                $rolePermission = new RolePermission();
                $rolePermission->project_id = $model->type == Role::TYPE_NOMAL ? $model->project_id : 0;
                $rolePermission->role_id = $role->id;
                $rolePermission->permission_id = $row;
                $rolePermission->permission_type = RolePermission::PERMISSION_TYPE_MENU;
                $rolePermission->save();
            }

            // 2-2.添加角色动作权限
            foreach ($model->getAddActionIds() as $row) {
                $rolePermission = new RolePermission();
                $rolePermission->project_id = $model->type == Role::TYPE_NOMAL ? $model->project_id : 0;
                $rolePermission->role_id = $role->id;
                $rolePermission->permission_id = $row;
                $rolePermission->permission_type = RolePermission::PERMISSION_TYPE_ACTION;
                $rolePermission->save();
            }

            // 2-3.添加角色模块权限
            foreach ($model->getAddModuleIds() as $row) {
                $rolePermission = new RolePermission();
                $rolePermission->project_id = $model->type == Role::TYPE_NOMAL ? $model->project_id : 0;
                $rolePermission->role_id = $role->id;
                $rolePermission->permission_id = $row;
                $rolePermission->permission_type = RolePermission::PERMISSION_TYPE_MODULE;
                $rolePermission->save();
            }

            $transaction->commit();

            return ['id' => $role->id];
        } catch (\Exception $e) {
            $transaction->rollBack();

            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 编辑角色
     *
     * @param RoleForm $model
     * @return array|mixed
     */
    public function edit(RoleForm $model)
    {
        try {
            $transaction = Yii::$app->db->beginTransaction();

            $role = $model->getRole();

            // 1.更新角色
            $attributes = [
                'name' => $model->name,
                'desc' => $model->desc,
                'status' => $model->status,
            ];
            Role::updateAll($attributes, ['id' => $model->id]);

            // 2-1.删除角色菜单权限
            RolePermission::deleteAll([
                'project_id' => $role->type == Role::TYPE_NOMAL ? $model->project_id : 0,
                'role_id' => $model->id,
                'permission_id' => $model->getDeleteMenuIds(),
                'permission_type' => RolePermission::PERMISSION_TYPE_MENU,
            ]);

            // 2-2.删除角色动作权限
            RolePermission::deleteAll([
                'project_id' => $role->type == Role::TYPE_NOMAL ? $model->project_id : 0,
                'role_id' => $model->id,
                'permission_id' => $model->getDeleteActionIds(),
                'permission_type' => RolePermission::PERMISSION_TYPE_ACTION,
            ]);

            // 2-3.删除角色模块权限
            RolePermission::deleteAll([
                'project_id' => $role->type == Role::TYPE_NOMAL ? $model->project_id : 0,
                'role_id' => $model->id,
                'permission_id' => $model->getDeleteModuleIds(),
                'permission_type' => RolePermission::PERMISSION_TYPE_MODULE,
            ]);

            // 3-1.添加角色菜单权限
            foreach ($model->getAddMenuIds() as $row) {
                $rolePermission = new RolePermission();
                $rolePermission->project_id = $role->type == Role::TYPE_NOMAL ? $model->project_id : 0;
                $rolePermission->role_id = $model->id;
                $rolePermission->permission_id = $row;
                $rolePermission->permission_type = RolePermission::PERMISSION_TYPE_MENU;
                $rolePermission->save();
            }

            // 3-2.添加角色动作权限
            foreach ($model->getAddActionIds() as $row) {
                $rolePermission = new RolePermission();
                $rolePermission->project_id = $role->type == Role::TYPE_NOMAL ? $model->project_id : 0;
                $rolePermission->role_id = $model->id;
                $rolePermission->permission_id = $row;
                $rolePermission->permission_type = RolePermission::PERMISSION_TYPE_ACTION;
                $rolePermission->save();
            }

            // 3-3.添加角色模块权限
            foreach ($model->getAddModuleIds() as $row) {
                $rolePermission = new RolePermission();
                $rolePermission->project_id = $role->type == Role::TYPE_NOMAL ? $model->project_id : 0;
                $rolePermission->role_id = $model->id;
                $rolePermission->permission_id = $row;
                $rolePermission->permission_type = RolePermission::PERMISSION_TYPE_MODULE;
                $rolePermission->save();
            }

            $transaction->commit();

            return ['id' => $model->id];
        } catch (\Exception $e) {
            $transaction->rollBack();

            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 删除角色
     *
     * @param RoleForm $model
     * @return array|mixed
     */
    public function delete(RoleForm $model)
    {
        try {
            // 1.更新角色
            $attributes = [
                'status' => Role::STATUS_DELETE,
            ];
            Role::updateAll($attributes, ['id' => $model->id]);

            return ['id' => $model->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 编辑角色状态
     *
     * @param RoleForm $model
     * @return array|mixed
     */
    public function editStatus(RoleForm $model)
    {
        try {
            // 1.更新角色
            $attributes = [
                'status' => $model->status,
            ];
            Role::updateAll($attributes, ['id' => $model->id]);

            return ['id' => $model->id];
        } catch (\Exception $e) {
            return CommonHelper::api(422, $e->getMessage());
        }
    }

}
